package org.gcb.core.model;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeMap;

/**
 *
 * @author Jason
 */
public class Equipment {
    static final Comparator<EArmorSlot> slotComparator = new Comparator<EArmorSlot>() {

        @Override
        public int compare(EArmorSlot o1, EArmorSlot o2) {
            return o1.compareTo(o2);//TODO might need to adjust the calculation
        }
    };
    private final Worn worn = new Worn();
    private final Carried carried = new Carried();
    private final Toon toon;

    public Equipment(Toon toon) {
        this.toon = toon;
    }

    public Carried getCarried() {
        return carried;
    }

    public Worn getWorn() {
        return worn;
    }


    public class Worn extends TreeMap<EArmorSlot, Armor>{
//        private TreeMap<EArmorSlot, Armor> emptySlots;
        private Worn() {
            super(slotComparator);
//            emptySlots = new TreeMap<EArmorSlot, Armor>();
            EArmorSlot[] slots = EArmorSlot.values();
//            Armor armor;
            for (EArmorSlot armorSlot : slots) {
//                armor = new Armor("", "", 0.0, armorSlot, 0, 0);
//                emptySlots.put(armorSlot, armor);
                put(armorSlot, null);
            }
        };

        /**
         * This calculation goes through all the equipped items and sums up their armor bonuses.<br>
         * As per some of the calculations based on {@link Defense#getScore()}, the shield bonus will be available through {@code get(EArmorSlot.SHIELD).getArmorBonus();}<br>
         * Alternatively we can implement a boolean flag to include/exclude the shield bonus.
         * @return
         */
        public Integer getArmorBonus() {
            Integer armorBonus = 0;
            Armor armor;
            for (EArmorSlot slot : EArmorSlot.values()) {
                if(slot==EArmorSlot.ARMS)
                    continue;
                armor = get(slot);
                armorBonus += armor==null?0:armor.getArmorBonus();
            }
            return armorBonus;
        }

        /**
         *
         * @return
         */
        public Integer getCheckPenalty() {
            Integer checkPenalty = 0;
            Armor armor;
            for (EArmorSlot slot : EArmorSlot.values()) {
                armor = get(slot);
                checkPenalty += armor==null?0:armor.getCheckPenalty();
            }
            return checkPenalty;
        }

        /**
         *
         * @return
         */
        public Integer getSpeedPenalty() {
            Integer speedPenalty = 0;
            Armor armor;
            for (EArmorSlot slot : EArmorSlot.values()) {
                armor = get(slot);
                speedPenalty += armor==null?0:armor.getSpeedPenalty();
            }
            return speedPenalty;
        }

        /**
         * Calculated the same as {@link Carried#getWeight() }. However,
         * instead of looping over all the {@link Item}s there is a defined
         * set of {@link Armor} pieces that contribute to this weight
         * calculation.
         * @return a double value.
         */
        public Double getWeight() {
            Double weight = 0.0;
            EArmorSlot[] slots = EArmorSlot.values();
            Armor armor;
            for (EArmorSlot eArmorSlot : slots) {
                armor = get(eArmorSlot);
                weight += armor==null?0:armor.getWeight();
            }
            return weight;
        }

        public boolean isEmpty(EArmorSlot slot) {
            Armor armor = super.get(slot);
            return armor==null;
        }
    }

    /**
     * Class used to model what items a toon is carrying.
     */
    public class Carried extends ArrayList<Item> {
        /** */
        private Carried() {};

        /**
         * Calculates the weight of <b>only</b> the {@link Item}s by the toon.
         * @return a double value.
         */
        public Double getWeight() {
            Double weight = 0.0;
            Iterator<Item> it = this.iterator();
            Item item;
            while (it.hasNext()) {
                item = it.next();
                weight += item.getWeight();
            }
            return weight;
        }

        public Double getNormalCarryWeight() {
            Integer str = toon.getAbilities().get(AbilityType.STR).getModifier();
            if (str<0) {
                str=0;
            }
            return str*10.0;
        }

        public Double getMaxCarryWeight() {
            Integer str = toon.getAbilities().get(AbilityType.STR).getModifier();
            if (str<0) {
                str=0;
            }
            return str*20.0;
        }

        public Double getMaxDragWeight() {
            Integer str = toon.getAbilities().get(AbilityType.STR).getModifier();
            if (str<0) {
                str=0;
            }
            return str*50.0;
        }
    }
}